using System.Web.Mvc;
using ExtendedMvc.Common.Diagnostics;
using ExtendedMvc.Html;

namespace ExtendedMvc.Elements {
	public abstract class Element<T> : IElement where T : Element<T>, IElement {
		private string _id;
		private string _addAfter = string.Empty;
		private string _addBefore = string.Empty;

		public TagBuilder Builder { get; internal set; }

		protected string id { get { return _id; } }

		protected Element(string tag, string id = null) {
			Check.Argument.IsNotNullOrEmpty(tag, "tag");
			Builder = new TagBuilder(tag);
			Id(id);
		}

		public virtual T Id(string value) {
			_id = HtmlAttribute.ClearInvalidChars(value);
			return (T)this;
		}

		public virtual T AddBefore(string value) {
			if (!string.IsNullOrEmpty(value)) _addBefore = value + _addBefore;
			return (T)this;
		}

		public virtual T AddAfter(string value) {
			if (!string.IsNullOrEmpty(value)) _addAfter = _addAfter + value;
			return (T)this;
		}

		public virtual T WrapWith(string tag) {
			var element = new TagBuilder(tag);
			AddBefore(element.ToString(TagRenderMode.StartTag));
			AddAfter(element.ToString(TagRenderMode.EndTag));
			return (T)this;
		}

		#region Attribute Handling
		protected virtual void SetAttribute(string name, object value) {
			Check.Argument.IsNotNullOrWhiteSpace(name, "name");
			((IElement)this).SetAttr(name, value);
		}

		protected virtual void MergeAttribute(string name, object value) {
			Check.Argument.IsNotNullOrWhiteSpace(name, "name");
			((IElement)this).MergeAttr(name, value);
		}

		//protected virtual void RemoveAttribute(string name) {
		//    Check.Argument.IsNotNullOrWhiteSpace(name, "name");
		//    ((IElement)this).RemoveAttr(name);
		//}

		//protected virtual string GetAttribute(string name) {
		//    Check.Argument.IsNotNullOrWhiteSpace(name, "name");
		//    return ((IElement)this).GetAttr(name);
		//}
		#endregion

		protected virtual TagRenderMode TagRenderMode { get { return TagRenderMode.Normal; } }

		protected virtual void SetId() {
			if (!string.IsNullOrWhiteSpace(_id)) SetAttribute(HtmlAttribute.Id, _id);
		}

		protected virtual void Prepare() { }

		protected virtual void SetContent() { }

		public override string ToString() {
			SetId();
			Prepare();
			SetContent();
			return _addBefore + Builder.ToString(this.TagRenderMode) + _addAfter;
		}

		public virtual MvcHtmlString Render() {
			return MvcHtmlString.Create(this.ToString());
		}

		#region Explicit IElement members

		//void IElement.RemoveAttr(string name) { Builder.Attributes.Remove(name); }

		void IElement.SetAttr(string name, object value) {
			var valueString = value == null ? null : value.ToString();
			Builder.MergeAttribute(name, valueString, true);
		}

		void IElement.MergeAttr(string name, object value) {
			var valueString = value == null ? null : value.ToString();
			Builder.MergeAttribute(name, valueString);
		}

		//string IElement.GetAttr(string name) {
		//    string result;
		//    Builder.Attributes.TryGetValue(name, out result);
		//    return result;
		//}

		TagRenderMode IElement.TagRenderMode { get { return TagRenderMode; } }

		#endregion
	}
}